#include <iostream>
#include "include/core/SkCanvas.h"
#include "include/core/SkBitmap.h"
#include "include/core/SkEncodedImageFormat.h"
#include "include/core/SkImageEncoder.h"
#include "include/core/SkStream.h"
#include "include/core/SkFont.h"
#include "include/core/SkShader.h"
#include "include/effects/SkGradientShader.h"
#include "include/core/SkImage.h"
#include "include/codec/SkCodec.h"
#include "include/core/SkSurface.h"

void saveBitmapToFile(SkBitmap &bitmap, const char* fileName){
    SkFILEWStream stream(fileName);
    SkEncodeImage(&stream, bitmap, SkEncodedImageFormat::kJPEG, 80);
    std::cout << "saveBitmapToFile: " << fileName << std::endl;
}

void blendClear(){
    SkImageInfo imageInfo = SkImageInfo::MakeN32(250, 250, SkAlphaType::kPremul_SkAlphaType);
    SkBitmap bitmap;
    bitmap.setInfo(imageInfo);
    bitmap.allocPixels();
    SkCanvas canvas = SkCanvas(bitmap);
    canvas.saveLayer(nullptr, nullptr);
    canvas.drawColor(SK_ColorYELLOW, SkBlendMode::kClear);      // kClear was ignored
    canvas.drawColor(SK_ColorWHITE, SkBlendMode::kSrc);

    SkPaint paint;
    for (auto color: {SK_ColorRED, SK_ColorBLUE, SK_ColorGREEN}){
        SkColor colors[] = {color, SkColorSetA(color, 0)};
        paint.setShader(SkGradientShader::MakeRadial({64, 64}, 100, colors, nullptr,
                SK_ARRAY_COUNT(colors), SkTileMode::kClamp));
        canvas.drawCircle(64, 64, 100, paint);
        canvas.translate(64, 64);
    }

    canvas.restore();
    saveBitmapToFile(bitmap, "blend_clear.jpg");
}

void clipRect(){
    SkImageInfo imageInfo = SkImageInfo::MakeN32(1420, 954, SkAlphaType::kPremul_SkAlphaType);
    SkBitmap bitmap;
    bitmap.setInfo(imageInfo);
    bitmap.allocPixels();

    SkCanvas canvas = SkCanvas(bitmap);
    canvas.clear(SK_ColorGREEN);
    canvas.saveLayer(nullptr, nullptr);
    sk_sp<SkData> data = SkData::MakeFromFileName("../beauty.jpg");
    auto codec = SkCodec::MakeFromData(data);
    if (codec == nullptr){
        std::cout << "MakeFromData failed" << std::endl;
        exit(-1);
    }
    SkBitmap picture;
    picture.setInfo(codec->getInfo());
    picture.allocPixels();
    codec->getPixels(codec->getInfo(), picture.getPixels(), picture.rowBytes());

    canvas.drawBitmap(picture, 10, 10);

    canvas.restore();
    saveBitmapToFile(bitmap, "beauty.jpg");
}

void drawImage(){
    SkImageInfo imageInfo = SkImageInfo::MakeN32(1420, 954, SkAlphaType::kPremul_SkAlphaType);
    SkBitmap bitmap;
    bitmap.setInfo(imageInfo);
    bitmap.allocPixels();

    SkCanvas canvas = SkCanvas(bitmap);
    canvas.clear(SK_ColorYELLOW);

    sk_sp<SkData> data = SkData::MakeFromFileName("../beauty.jpg");
    sk_sp<SkImage> image = SkImage::MakeFromEncoded(data);
    canvas.drawImage(image, 10, 10);

    saveBitmapToFile(bitmap, "beauty-image.jpg");
}

void drawSurface(){
    sk_sp<SkSurface> rasterSurface = SkSurface::MakeRasterN32Premul(1420, 954);
    SkCanvas* canvas = rasterSurface->getCanvas();
    canvas->clear(SK_ColorBLUE);

    sk_sp<SkData> data = SkData::MakeFromFileName("../beauty.jpg");
    sk_sp<SkImage> image = SkImage::MakeFromEncoded(data);
    canvas->drawImage(image, 10, 10);

    sk_sp<SkData> compressData = rasterSurface->makeImageSnapshot()->encodeToData(SkEncodedImageFormat::kJPEG, 80);
    SkFILEWStream stream("beauty-surface.jpg");
    stream.write(compressData->data(), compressData->size());
}

int main(){
    blendClear();
    clipRect();
    drawImage();
    drawSurface();
}
